4-6 rPr磢?

我們也可定義字元的重複次數,整理如下:

通用表示法說明
a?零或一個 a(若要比對? 字元,請使用 \?)
a+一或多個 a(若要比對+ 字元,請使用 \+)
a*零或多個 a(若要比對* 字元,請使用 \*)
a{4}四個 a
a{5,10}五至十個 a
a{5,}至少五個 a
a{,3}至多三個 a
a.{5}ba 和 b中間夾五個(非換行)字元

使用上表與字元重複次數相關的特殊符號,我們可以從字串「I like Chapter 2, Chapter 10, and Chapter 25 of this book!」抓出「Chapter 2」、「Chapter 10」,以及「Chapter 25」,請見下列範例:

Example 1: 04-通用運算式/regExp08.mstring = 'I like Chapter 2, Chapter 10, and Chapter 25 of this book!'; pattern = 'Chapter [1-9][0-9]?'; [start, finish] = regexp(string, pattern); fprintf('Matched substrings:\n'); for i=1:length(start) fprintf('\t%d: %s\n', i, string(start(i):finish(i))); endMatched substrings: 1: Chapter 2 2: Chapter 10 3: Chapter 25

若要抓出信用卡號碼,可見下列範例:

Example 2: 04-通用運算式/regExp12.mstring = 'My credit number is "1234-5678-9012-3456".'; pattern = '\d{4}-\d{4}-\d{4}-\d{4}'; [start, finish] = regexp(string, pattern); fprintf('Matched substrings:\n'); for i=1:length(start) fprintf('\t%d: %s\n', i, string(start(i):finish(i))); endMatched substrings: 1: 1234-5678-9012-3456

如果要比對身份證字號,可用下列範例:

Example 3: 04-通用運算式/regExp05.mstring = 'My Id number is F123765431'; pattern = '[A-Z]\d{9}'; start = regexp(string, pattern)start = 17

此回傳結果代表 F123765431 在 string 變數的開始位置。在上述範例中, [A-Z] 代表由 A 至 Z 的所有可能英文字母,\d 代表由 0 至 9 的數目字(事實上也可以寫成 [0-9]),{9} 則代表需要有九個數目字,因此 「[A-Z]\d{9}」 就代表可以比對身份證字號的通用式。

Hint
事實上,身份證字號本身就有內在的編碼規則,這些規則和使用者的性別有關,還包含一個檢查碼,並非簡簡單單地由一個英文字母加上九個數字所構成。有關於身份證字號的編碼規則,可以在網路的搜尋引擎(例如 www.google.com)上查到很多相關說明。

若要在一個字串中,找出「在 b 與 t 中間夾二或三個母音的子字串」,可見下列範例:

Example 4: 04-通用運算式/regExp09.mstring = 'bt bat bet ban bit boat beet berp boaet baeiout'; pattern = 'b[aeiou]{2,3}t'; [start, finish] = regexp(string, pattern); fprintf('Matched substrings:\n'); for i=1:length(start) fprintf('\t%d: %s\n', i, string(start(i):finish(i))); endMatched substrings: 1: boat 2: beet 3: boaet

我們也可以利用小刮號,進行重複字串的比對。例如前面提到的信用卡號碼,通用式可以寫成「\d{4}-\d{4}-\d{4}-\d{4}」,也可以利用小括弧寫成「(\d{4}-){3}\d{4}」(\d{4}- 重複三次,再加上 \d{4}),請見下列範例:

Example 5: 04-通用運算式/regExp18.mstring = 'Two cards: 1234-5678-9012-3456 and 0987-6543-2109-8765'; pattern = '(\d{4}-){3}\d{4}'; [start, finish] = regexp(string, pattern); fprintf('Matched substrings:\n'); for i=1:length(start) fprintf('\t%d: %s\n', i, string(start(i):finish(i))); endMatched substrings: 1: 1234-5678-9012-3456 2: 0987-6543-2109-8765

特別要注意的是,在通用式的比對過程中,所採用的方法是「最大比對(Maximal Match)或是」「貪心比對」(Greedy Match),因此會盡量「貪」到越多的字元越好,例如,若使用通用式 'foo.*bar' 來比對字串 'The food is under the bar in the barn.',所比對到的是長字串 ‘food is under the bar in the bar’,而不是另一個符合比對標準的短字串 ‘food is under the bar’。若要使通用式進行極小比對(Minimal Match),也就是在符合比對的條件下,選擇最短的字串,那麼就要在星號之後加上問號,請見下列範例:

Example 6: 04-通用運算式/regExp19.mstring = 'The food is under the bar in the barn.'; pattern1 = 'foo.*bar'; [start, finish] = regexp(string, pattern1); fprintf('\tGreedy match: %s\n', string(start:finish)); pattern2 = 'foo.*?bar'; [start, finish] = regexp(string, pattern2); fprintf('\tMinimal match: %s\n', string(start:finish)); Greedy match: food is under the bar in the bar Minimal match: food is under the bar

Hint
各位讀者可以發現,問號在通用式的意義是和上下文相關(Context Dependent)的,可以分兩類情況來說明:
  1. 如果問號接在一般字元之後,代表「比對前一個字元零次或一次」。
  2. 如果問號接在星號或加號之後,代表「極小比對」。


MATLAB程式設計:進階篇